#!/usr/bin/env python


import wx
from time import strftime, localtime

from regulator import Regulator
from regulator import EVT_SERIAL_DATA
from regulator import EVT_SERIAL_ERROR

from settings import Settings, SettingsDialog
from stats import Stats, StatsDialog
from logger import EventLogger, EventLoggerDialog
from graph import GraphPanel

ID_SETTINGS = wx.NewId()
ID_EXIT = wx.NewId()
ID_STATS = wx.NewId()
ID_ERRORS = wx.NewId()
ID_EVENTS = wx.NewId()

       
class RegFrame(wx.Frame):
           
    def __init__(self, *args, **kwargs):
        
        wx.Frame.__init__(self, *args, **kwargs)
        
        self.settings = Settings()
        self.panel = wx.Panel(self)
        self.SetSize((650, 500))
        
        self.logger = EventLogger()
        self.stats = Stats()
        
        self.device = Regulator(win = self, port=self.settings.serial_port, baudrate=9600, timeout=2.5)
        
        self.graph = GraphPanel(self)
        
        self.Bind(EVT_SERIAL_DATA, self.Update)
        self.Bind(EVT_SERIAL_ERROR, self.SerialError)
    
        self.current_temp     = 0
        self.current_humidity = 0
        self.fan_status       = False
        self.heater_status    = False                          
        self.light_status     = False
        self.pump_status      = False
    
        self.__create_ui()
        self.__attach_events()
        #self.Fit()         
        #self.SetMinSize(self.GetSize())
        
    def __create_ui(self):
        
        self.LED_ON = wx.Image("images/green-on-16.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        self.LED_OFF = wx.Image("images/red-on-16.png", wx.BITMAP_TYPE_ANY).ConvertToBitmap()
        
        #Menu Bar
        self.frame_menubar = wx.MenuBar()
        self.SetMenuBar(self.frame_menubar)
        file_menu = wx.Menu()
        file_menu.Append(ID_SETTINGS, "&Settings", "Edit Settings", wx.ITEM_NORMAL)
        file_menu.AppendSeparator()
        file_menu.Append(ID_EXIT, "&Exit", "Exit Application", wx.ITEM_NORMAL)
        self.frame_menubar.Append(file_menu, "&File")
        
        view_menu = wx.Menu()
        view_menu.Append(ID_STATS, "&Statistics", '', wx.ITEM_NORMAL)
        view_menu.Append(ID_EVENTS, "&Event Logs", '',  wx.ITEM_NORMAL)
        self.frame_menubar.Append(view_menu, "&View")
        
        #Menu Bar

        self.container = wx.BoxSizer(wx.VERTICAL)
        self.top_row = wx.BoxSizer(wx.HORIZONTAL)
        
        led_box = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Status"), wx.VERTICAL) 
        light_box = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Water"), wx.VERTICAL)
        stats_box = wx.StaticBoxSizer(wx.StaticBox(self, -1, "Current"), wx.VERTICAL)
        
        stats_box.SetMinSize((170,180))
        light_box.SetMinSize((225,180))
        led_box.SetMinSize((225,180))
        
        self.top_row.Add(led_box, 0, wx.ALIGN_CENTER|wx.ALL , 5)
        self.top_row.Add(stats_box, 0, wx.ALIGN_CENTER|wx.ALL, 5)
        self.top_row.Add(light_box, 0, wx.ALIGN_CENTER|wx.ALL, 5)     
        
        self.container.Add(self.top_row)
        self.container.Add(self.graph)
        
        self.day_label = wx.StaticText(self.panel, label="Loading", style=wx.ALIGN_CENTER)
        self.time_label = wx.StaticText(self.panel, label="Date&Time",style=wx.ALIGN_CENTER)
        
        light_box.Add(self.day_label)
        light_box.Add(self.time_label)
        
#_________________________________________________________________________________________________    
        big_font = wx.Font(15, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
        big_font1 = wx.Font(15.5, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
        big_font2 = wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL)
        big_font3 = wx.Font(10, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD)
        
        self.week_label = wx.StaticText(self.panel, label="WEEK") 
        self.week_label.SetFont(big_font1)
        self.week_label_label = wx.StaticText(self.panel, label="   1")  
        self.week_label_label.SetFont(big_font1)  
        week_sizer = wx.BoxSizer(wx.HORIZONTAL)
        week_sizer.Add(self.week_label, 1, wx.ALL, 0)
        week_sizer.Add(self.week_label_label, 1, wx.ALL, 0)
        stats_box.Add(week_sizer)        

        self.temp_label = wx.StaticText(self.panel, label="   ") 
        self.temp_label.SetFont(big_font)
        self.temp_label_label = wx.StaticText(self.panel, label="  'C   ")  
        self.temp_label_label.SetFont(big_font3)  
        #temp_sizer = wx.BoxSizer(wx.HORIZONTAL)
        #temp_sizer.Add(self.temp_label, 1, wx.ALL, 0)
        #temp_sizer.Add(self.temp_label_label, 1, wx.ALL, 0)
        #stats_box.Add(temp_sizer)
            
        self.hum_label = wx.StaticText(self.panel, label="   ")
        self.hum_label.SetFont(big_font) 
        self.hum_label_label = wx.StaticText(self.panel, label="  %")
        self.hum_label_label.SetFont(big_font3)
        self.hum_label_label_label = wx.StaticText(self.panel, label="Humidity")
        self.hum_label_label_label.SetFont(big_font2)
        temphum_sizer = wx.BoxSizer(wx.HORIZONTAL)
        temphum_sizer.Add(self.temp_label, 1, wx.ALL, 0)
        temphum_sizer.Add(self.temp_label_label, 1, wx.ALL, 0)
        temphum_sizer.Add(self.hum_label, 1, wx.ALL, 0)
        temphum_sizer.Add(self.hum_label_label, 0.5, wx.ALL, 0) 
        temphum_sizer.Add(self.hum_label_label_label, 0.9, wx.ALL, 0) 
        stats_box.Add(temphum_sizer)
        
        self.ph_label = wx.StaticText(self.panel, label="PH")
        self.ph_label.SetFont(big_font) 
        self.ph_label_label = wx.StaticText(self.panel, label="5.5 ")
        self.ph_label_label.SetFont(big_font)
        ph_sizer = wx.BoxSizer(wx.HORIZONTAL)
        ph_sizer.Add(self.ph_label, 1, wx.ALL, 0)
        ph_sizer.Add(self.ph_label_label, 1, wx.ALL, 0)
        stats_box.Add(ph_sizer)
        
        self.ec_label = wx.StaticText(self.panel, label="EC")
        self.ec_label.SetFont(big_font) 
        self.ec_label_label = wx.StaticText(self.panel, label="850")
        self.ec_label_label.SetFont(big_font)
        self.ec_label_label_label = wx.StaticText(self.panel, label="us ")
        self.ec_label_label_label.SetFont(big_font2)
        ecph_sizer = wx.BoxSizer(wx.HORIZONTAL)
        ecph_sizer.Add(self.ec_label, 1, wx.ALL, 0)
        ecph_sizer.Add(self.ec_label_label, 1, wx.ALL, 0)
        ecph_sizer.Add(self.ec_label_label_label, 1, wx.ALL, 0)
        #ecph_sizer.Add(self.ph_label, 1, wx.ALL, 0)
        #ecph_sizer.Add(self.ph_label_label, 1, wx.ALL, 0)  
        stats_box.Add(ecph_sizer)
        
        self.c02_label = wx.StaticText(self.panel, label="CO2")
        self.c02_label.SetFont(big_font)
        self.c02_label_label = wx.StaticText(self.panel, label="1600")
        self.c02_label_label.SetFont(big_font) 
        self.c02_label_label_label = wx.StaticText(self.panel, label="ppm ")
        self.c02_label_label_label.SetFont(big_font)
        c02_sizer = wx.BoxSizer(wx.HORIZONTAL)
        c02_sizer.Add(self.c02_label, 1, wx.ALL, 0)
        c02_sizer.Add(self.c02_label_label, 1, wx.ALL, 0)
        c02_sizer.Add(self.c02_label_label_label, 1, wx.ALL, 0)
        stats_box.Add(c02_sizer)
        
    # self.SetSizer(self.container)
        
    #---------------------------------------------------------------------------      
    #Button
        self.fan_label = wx.Button(self.panel, label="Exhaust", pos=(75, 60))
        self.heater_label = wx.Button(self.panel, label="Heater", pos=(75, 80))
        self.light_label = wx.Button(self.panel, label="Light", pos=(75, 100))
        self.pump_label = wx.Button(self.panel, label="Pump", pos=(75, 120))
    #Button 
       
        self.auto_fan    = wx.Button(self.panel, label="AUTO", pos=(175, 60))
        self.auto_heater = wx.Button(self.panel, label="AUTO", pos=(175, 80))
        self.auto_light  = wx.Button(self.panel, label="AUTO", pos=(175, 100))
        self.auto_pump   = wx.Button(self.panel, label="AUTO", pos=(175, 120))
        #self.Bind(wx.EVT_BUTTON,self.button1,button1) #cbtn.Bind(wx.EVT_BUTTON,exit)
        
        self.fanIO_LED = wx.StaticBitmap(self, -1, self.LED_OFF)
        self.heaterIO_LED = wx.StaticBitmap(self, -1, self.LED_OFF)
        self.lightIO_LED = wx.StaticBitmap(self, -1, self.LED_OFF)
        self.pumpIO_LED = wx.StaticBitmap(self, -1, self.LED_OFF)
        
        fan_sizer = wx.BoxSizer(wx.HORIZONTAL)
        fan_sizer.Add(self.fan_label, 0, wx.ALL, 4)
        fan_sizer.Add(self.fanIO_LED, 0, wx.ALL, 4)
        fan_sizer.Add(self.auto_fan, 0, wx.ALL, 4)
        led_box.Add(fan_sizer)
        
        heater_sizer = wx.BoxSizer(wx.HORIZONTAL)
        heater_sizer.Add(self.heater_label, 0, wx.ALL, 4)
        heater_sizer.Add(self.heaterIO_LED, 0, wx.ALL, 4)
        heater_sizer.Add(self.auto_heater, 0, wx.ALL, 4)
        led_box.Add(heater_sizer)
        
        light_sizer = wx.BoxSizer(wx.HORIZONTAL)
        light_sizer.Add(self.light_label, 0, wx.ALL, 4)
        light_sizer.Add(self.lightIO_LED, 0, wx.ALL, 4)
        light_sizer.Add(self.auto_light, 0, wx.ALL, 4)
        led_box.Add(light_sizer)
        
        pump_sizer = wx.BoxSizer(wx.HORIZONTAL)
        pump_sizer.Add(self.pump_label, 0, wx.ALL, 4)
        pump_sizer.Add(self.pumpIO_LED, 0, wx.ALL, 4)
        pump_sizer.Add(self.auto_pump, 0, wx.ALL, 4)
        led_box.Add(pump_sizer)
        
        
        #self.fanIO_label = wx.StaticText(self.panel, label="__", pos=(30, 60))
        #self.heaterIO_label = wx.StaticText(self.panel, label="__", pos=(30, 80))
        #self.lightIO_label = wx.StaticText(self.panel, label="__", pos=(30, 100))
        #self.pumpIO_label = wx.StaticText(self.panel, label="__", pos=(30, 120)) 
        
        self.SetSizer(self.container)

        #self.Layout()
                 
    def __update_ui(self):
        self.time_label.SetLabel(strftime("%a, %d %b %H:%M:%S", localtime()))
        
        self.heaterIO_LED.SetBitmap(self.LED_ON if self.heater_status else self.LED_OFF)
        self.fanIO_LED.SetBitmap(self.LED_ON if self.fan_status else self.LED_OFF)
        self.lightIO_LED.SetBitmap(self.LED_ON if self.light_status else self.LED_OFF)
        self.pumpIO_LED.SetBitmap(self.LED_ON if self.pump_status else self.LED_OFF)
                
        self.temp_label.SetLabel(str(self.current_temp))
        self.hum_label.SetLabel(str(self.current_humidity))

    def __attach_events(self):
        #Menu Bar Events
        self.Bind(wx.EVT_MENU, self.OnSettings, id = ID_SETTINGS)
        self.Bind(wx.EVT_MENU, self.OnStats, id = ID_STATS)
        self.Bind(wx.EVT_MENU, self.OnLogs, id = ID_EVENTS)
        
        self.Bind(wx.EVT_MENU, self.OnExit, id = ID_EXIT)
        self.Bind(wx.EVT_CLOSE, self.OnExit)

    def OnSettings(self, event):
        dialog = SettingsDialog(None, -1, "", settings = self.settings)
        dialog.ShowModal()
        dialog.Destroy()
    
    def OnLogs(self, event):
        dialog = EventLoggerDialog(None, -1, "", logs = self.logger)
        dialog.ShowModal()
        dialog.Destroy()
        
    def OnStats(self, event):
        dialog = StatsDialog(None, -1, "", stats = self.stats)
        dialog.ShowModal()
        dialog.Destroy()
    
    def OnExit(self, event):
        self.device.RegThread.Stop()
        self.Destroy()
#FAN*controls temp and humidity      
    def ControlFan(self):
        if  self.current_temp >= self.fanon_temp :
            self.device.OnFan()

        elif self.current_humidity >= self.fanon_hum : 
            self.device.OnFan()
          
        elif self.current_temp <= self.fanoff_temp and self.current_humidity <= self.fanoff_hum:
            self.device.OffFan()#self.ToggleFanOff()
              
           

#HEATER*controls temp           
    def ControlHeater(self):
        if self.current_temp <= self.heateron_temp:
            self.device.OnHeater()
            
        elif self.current_temp >= self.heateroff_temp:
            self.device.OffHeater()
            
    def Update(self, *event):
        
        self.SetTempDay = self.settings.set_temp_day
        self.SetTempNight = self.settings.set_temp_night
        self.LightOn = self.settings.light_on
        self.LightOff = self.settings.light_off
        self.SetHum = self.settings.set_hum

        hour  = float(strftime('%H'))
        day   = self.LightOn <= hour and hour <= 23 or hour >= 0 and self.LightOff > hour
        night = self.LightOn > hour and self.LightOff <= hour 

        if day :
            self.SetTemp = self.SetTempDay
            self.device.OnLight()
            #self.device.OnFan()
            self.day_label.SetLabel("DAY TIME")
        if night :
            self.device.OffLight()      
            self.day_label.SetLabel("NIGHT TIME")
            self.SetTemp = self.SetTempNight

        self.fanoff_temp    = self.SetTemp  + self.settings.fan_off_offset
        self.fanon_temp     = self.SetTemp + self.settings.fan_on_offset
        self.fanoff_hum     = self.SetHum - self.settings.fan_off_hum_offset
        self.fanon_hum      = self.SetHum - self.settings.fan_on_hum_offset
        self.heateroff_temp = self.SetTemp - self.settings.heater_off_offset
        self.heateron_temp  = self.SetTemp - self.settings.heater_on_offset

        self.current_temp     = self.device.current_temp
        self.current_humidity = self.device.current_humidity
        self.fan_status       = self.device.fan_status
        self.heater_status    = self.device.heater_status
        self.light_status     = self.device.light_status
        self.pump_status      = self.device.pump_status

        self.ControlHeater()
        self.ControlFan()
         
        self.__update_ui()
        self.stats.LogData(self.current_temp, self.current_humidity)
        
        self.graph.draw()


    #def ToggleFanOff (self):
        
    #    hour = float(strftime('%H'))
    #    day   = self.LightOn <= hour and hour <= 23 or hour >= 0 and self.LightOff > hour
    #    night = self.LightOn > hour and self.LightOff <= hour 

    #    if day :  
    #        self.device.OnFan()
           
    #    if night : 
    #        self.device.OffFan()

    def SerialError(self, evt):
        wx.MessageBox('Error: {0}'.format(evt.error), 'Error', wx.OK | wx.ICON_ERROR)
        self.logger.Log('ERROR', str(evt.error))
        self.device.RegThread.Stop()

    
if __name__ == '__main__':

    app = wx.App(redirect = False)
    frame = RegFrame(parent=None, title='Enviroment Regulator')
    frame.Show()
    app.MainLoop()    

